package com.astruyk.chordophone;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

/**
 * An adapter used to display a filtered list of chords.
 */
public class ChordListAdapter extends BaseAdapter implements Filterable{
	private final List<Chord> _allChords = new ArrayList<Chord>();
	private final List<Chord> _filteredChords = new ArrayList<Chord>();
	private final LayoutInflater _inflater;
	private final Object _lock = new Object();
	
	private ChordFilter _filter;
	
	public ChordListAdapter(Context context, List<Chord> chords){
		_inflater = LayoutInflater.from(context);
		_allChords.addAll(chords);
		_filteredChords.addAll(chords);
	}
	
	public ChordFilter getFilter(){
		if(_filter == null) { _filter = new ChordFilter(); }
		return _filter;
	}
	
	@Override
	public int getCount() {
		return _filteredChords.size();
	}

	@Override
	public Object getItem(int location) {
		return _filteredChords.get(location);
	}

	@Override
	public long getItemId(int location) {
		return location;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		Chord chord = _filteredChords.get(position);
		
		View view;
		if(convertView == null){
			view = _inflater.inflate(R.layout.chord_list_item, parent, false);
		}else{
			view = convertView;
		}
		
		view.setBackgroundColor(chord.getColor());
		
		TextView chordTextView = (TextView)view.findViewById(R.id.chord_list_item_chord);
		chordTextView.setText(chord.getName());
				
		TextView variantTextView = (TextView)view.findViewById(R.id.chord_list_item_variant);
		variantTextView.setText(chord.getVariant());
		
		CompactChordView previewView = (CompactChordView)view.findViewById(R.id.chord_list_item_preview);
		previewView.setChord(chord);
		
		return view;
	}
	
	@Override
	public boolean hasStableIds() {
		return false;
	}
	
	public class ChordFilter extends Filter {

		@Override
		protected FilterResults performFiltering(CharSequence constraint) {
			FilterResults results = new FilterResults();
			
			//Generate a copy of the original list for filtering
			List<Chord> chords = new ArrayList<Chord>();
			
			if(constraint == null || constraint.equals(CONSTRAINT_SEPARATOR)){
				//null indicates that the values should be reset
				synchronized(_lock)
				{
					chords.addAll(_allChords);
				}
			}else{
				//Decode the filter constraint into a chord/variant filter
				String[] filters = constraint.toString().split(CONSTRAINT_SEPARATOR);
				String chordFilter = "";
				String variantFilter = "";
				boolean onlyCommon = false;

				if(filters.length > 0){
					chordFilter = filters[0];
				}
				if(filters.length > 1){
					variantFilter = filters[1];
				}
				if(filters.length > 2){
					if(filters[2].equalsIgnoreCase("true")){
						onlyCommon = true;
					}
				}
				
				synchronized(_lock)
				{
					for(Chord c : _allChords){
						if(chordFilter != null
							&& chordFilter.length() > 0
							&& !c.getName().startsWith(chordFilter)){
							continue;
						}else if(variantFilter != null
							&& variantFilter.length() > 0
							&& !c.getVariant().startsWith(variantFilter)){
							continue;
						}else if(onlyCommon && !c.getIsCommon()){
							continue;
						}
						
						//If we get this far we passed the test!
						chords.add(c);
					}
				}
			}
			
			results.count = chords.size();
			results.values = chords;
			return results;
		}

		@SuppressWarnings("unchecked")
		@Override
		protected void publishResults(CharSequence constraint, FilterResults results) {
			List<Chord> filteredResults = (List<Chord>)results.values;
			_filteredChords.clear();
			_filteredChords.addAll(filteredResults);
			
			notifyDataSetChanged();
		}
	}
	
	/**
	 * The string used to separate chords and variants in a filter string.
	 */
	private static final String CONSTRAINT_SEPARATOR = ",";
	
	/**
	 * Generates a valid filter string that will match only chords
	 * that are of a particular chord root or variant type.
	 * @param chordName the name of the root chord to match against, can be null
	 * @param variant the name of the variant to match against, can be null
	 * @param onlyCommon true if only common chords should be shown, false if all chords should be shown
	 * @return a string that can be used to filter the elements in this adapter
	 */
	public static String buildFilterConstraint(String chordName, String variant, boolean onlyCommon){
		if(chordName == null) { chordName = ""; }
		if(variant == null) { variant = ""; }
		return chordName + CONSTRAINT_SEPARATOR + variant + CONSTRAINT_SEPARATOR + onlyCommon;
	}
}
